<template>
	<el-dialog :visible.sync="visible" width="50%" title="权限分配" 
		:close-on-click-modal="false" :close-on-press-escape="false"
		:modal-append-to-body="false" :append-to-body="true">
		<el-table size="small" border default-expand-all row-key="id"
			:data="permissionTrees" :indent="12"
			:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
			<el-table-column label="ID" prop="id" width="200"></el-table-column>
			<el-table-column :render-header="renderHeaderCheckbox">
				<template slot-scope="scope">
					<el-row>
						<el-col :span="4">
							<el-checkbox :value="checkedMap[scope.row.id]"
								:indeterminate="isIndeterminate(scope.row.id)"
								@change="selectPage(scope.row.id)">{{scope.row.label}}</el-checkbox>
						</el-col>
						<el-col :span="20">
							<el-row v-for="(action, i) in scope.row.actions" v-if="i % 4 == 0" :key="i">
								<el-col :span="6" v-for="j in 4" v-if="i + j - 1 < scope.row.actions.length" :key="i + j - 1">
									<el-checkbox :value="checkedMap[scope.row.actions[i + j - 1].id]"
										@change="selectAction(scope.row.actions[i + j - 1].id)">
										<el-tag size="mini">{{scope.row.actions[i + j - 1].label}}</el-tag>
									</el-checkbox>
								</el-col>
							</el-row>
						</el-col>
					</el-row>
				</template>
			</el-table-column>
		</el-table>
		<span slot="footer" class="dialog-footer">
			<el-button size="mini" @click="visible = false">取消</el-button>
			<el-button size="mini" type="primary" @click="submit">确定
				<i class="fa fa-save"></i>
			</el-button>
		</span>
	</el-dialog>
</template>

<script>
import request from '@/utils/request';
import store from '@/store';
import cfg from './js/';

export default {
	store: cfg.store,
	data() {
		return {
			visible: false,
			permissionTrees: [],
			permissionMap: {},
			checkedMap: {},
			roleId: null
		}
	},
	methods: {
		open(role) {
			for(let id in this.checkedMap) {
				this.$set(this.checkedMap, id, false);
			}
			role.permissionIds.forEach(id => {
				this.$set(this.checkedMap, id, true);
			});
			this.roleId = role.id;
			this.visible = true;
		},
		renderHeaderCheckbox() {
			return (
				<el-checkbox value={this.isOneChecked} 
					indeterminate={this.isOneChecked && !this.isAllChecked}
					onChange={this.selectAll}>
					全选
				</el-checkbox>		
			)
		},
		selectAction(id) {
			this.$set(this.checkedMap, id, !this.checkedMap[id]);
			let action = store.state.global.permissionMap[id];
			let parent = action.parent;
			let checked = false;
			for(let i = 0; i < parent.actions.length; i++) {
				let action = parent.actions[i];
				if(this.checkedMap[action.id]) {
					checked = true;
					break;
				}
			}
			if(checked) {
				while(parent != null) {
					this.$set(this.checkedMap, parent.id, true);
					parent = parent.parent;
				}
			} else {
				while(parent != null) {
					let tag = false;
					if(parent.children != null) {
						for(let i = 0; i < parent.children.length; i++) {
							let child = parent.children[i];
							if(this.checkedMap[child.id]) {
								tag = true;
								break;
							}
						}
					}
					if(tag == false && parent.actions != null) {
						for(let i = 0; i < parent.actions.length; i++) {
							let action = parent.actions[i];
							if(this.checkedMap[action.id]) {
								tag = true;
								break;
							}
						}
					}
					this.$set(this.checkedMap, parent.id, tag);
					parent = parent.parent;
				}
			}
		},
		selectPage(id) {
			let checked = false;
			if(this.checkedMap[id] == false || this.isIndeterminate(id) == true) {
				checked = true;
			} else {
				checked = false;
			}
			let queue = [];
			queue.push(store.state.global.permissionMap[id]);
			while(queue.length > 0) {
				let permission = queue.shift();
				this.$set(this.checkedMap, permission.id, checked);
				if(permission.actions) {
					permission.actions.forEach(action => {
						queue.push(action);
					});
				}
				if(permission.children) {
					permission.children.forEach(child => {
						queue.push(child);
					});
				}
			}
			let parent = store.state.global.permissionMap[id].parent;
			if(checked) {
				while(parent != null) {
					this.$set(this.checkedMap, parent.id, true);
					parent = parent.parent;
				}
			} else {
				while(parent != null) {
					let tag = false;
					if(parent.children != null) {
						for(let i = 0; i < parent.children.length; i++) {
							let child = parent.children[i];
							if(this.checkedMap[child.id]) {
								tag = true;
								break;
							}
						}
					}
					if(tag == false && parent.actions != null) {
						for(let i = 0; i < parent.actions.length; i++) {
							let action = parent.actions[i];
							if(this.checkedMap[action.id]) {
								tag = true;
								break;
							}
						}
					}
					this.$set(this.checkedMap, parent.id, tag);
					parent = parent.parent;
				}
			}
		},
		selectAll() {
			let checked = false;
			if(this.isAllChecked) {
				checked = false;
			} else {
				checked = true;
			}
			for(let id in this.checkedMap) {
				this.$set(this.checkedMap, id, checked);
			}
		},
		isIndeterminate(id) {
			if(this.checkedMap[id] == false) {
				return false;
			}
			let permission = store.state.global.permissionMap[id];
			if((permission.actions == null || permission.actions.length == 0) && 
				(permission.children == null || permission.children.length == 0)) {
				return false;
			}
			if(permission.actions != null) {
				for(let i = 0; i < permission.actions.length; i++) {
					let action = permission.actions[i];
					if(this.checkedMap[action.id] == false) {
						return true;
					}
				}
			}
			if(permission.children != null) {
				for(let i = 0; i < permission.children.length; i++) {
					let child = permission.children[i];
					if(this.checkedMap[child.id] == false || this.isIndeterminate(child.id)) {
						return true;
					}
				}
			}
		},
		submit() {
			let self = this;
			let loading = self.$loading({
				target: self.$el,
				lock: true,
				text: '分配权限中...',
				spinner: 'el-icon-loading',
				background: 'rgba(0, 0, 0, 0.7)'
			});
			let data = {
				id: this.roleId,
				permissions: []
			};
			for(let id in this.checkedMap) {
				if(this.checkedMap[id]) {
					let permission = store.state.global.permissionMap[id];
					permission && data.permissions.push({
						id: id, method: permission.method || '', url: permission.url || ''
					});
				}
			}
			let config = {};
			config.data = data;
			let action = store.state.global.permissionMap['sys:role:assignPermissions'];
			action.doAction(config).then(data => {
				for(let i = 0; i < self.$store.state.app.list.length; i++) {
					let e = self.$store.state.app.list[i];
					let element = data.element;
					if(e.id == element.id) {
						self.$store.state.app.list.splice(i, 1, element);
						break;
					}
				}
				self.$message({
					message: '分配权限成功',
					type: 'success',
					showClose: true
				});
				loading.close();
				self.visible = false;
			}).catch(error => {
				self.$message({
					message: '分配权限失败：' + error.detail.msg,
					type: 'error',
					showClose: true
				});
				loading.close();
			});
		}
	},
	computed: {
		isAllChecked() {
			for(let id in this.checkedMap) {
				if(!this.checkedMap[id]) {
					return false;
				}
			}
			return true;
		},
		isOneChecked() {
			for(let id in this.checkedMap) {
				if(this.checkedMap[id]) {
					return true;
				}
			}
			return false;
		}
	},
	created() {
		let pages = store.state.global.permissions.concat();
		let queue = [];
		let i = 0;
		while(i < pages.length || queue.length > 0) {
			if(queue.length == 0) {
				let page = pages[i++];
				queue.push(page);
			}
			let page = queue.shift();
			this.$set(this.checkedMap, page.id, false);
			page.actions && page.actions.forEach(action => {
				this.$set(this.checkedMap, action.id, false);
			});
			page.children && page.children.forEach(child => {
				queue.push(child);
			});
		}
		this.permissionTrees = pages;
	}
}
</script>